﻿using System;
using System.Windows.Input;
using Oxage.Common;
using Oxage.Services;

namespace Oxage.Commands
{
	public class DebugCommand : ICommand
	{
		#region Constructor
		public DebugCommand()
		{
			//TODO: Add BreakpointChanged events (when breakpoint added or removed)

			DebugService.CurrentProjectDebuggerChanged += (sender, e) =>
			{
				//Detach events from previous instance
				if (e.OldValue != null)
				{
					e.OldValue.IsDebuggingChanged -= (a, b) => { };
				}

			  //Attach events
				if (e.NewValue != null)
				{
					e.NewValue.IsDebuggingChanged += (a, b) => ViewHelper.Dispatch(() => OnCanExecuteChanged());
				}
			};

			if (DebugService.CurrentProjectDebugger != null)
			{
				//Track changes
				DebugService.CurrentProjectDebugger.IsDebuggingChanged += (a, b) => ViewHelper.Dispatch(() => OnCanExecuteChanged());
			}
		}
		#endregion

		#region ICommand Members
		public bool CanExecute(object parameter)
		{
			var debugger = DebugService.CurrentProjectDebugger;
			if (debugger == null)
			{
				return false;
			}

			var command = parameter as string;
			switch (command)
			{
				case "Start":
					return !debugger.IsDebugging;

				case "Stop":
					return debugger.IsDebugging;

				case "Step":
					return debugger.IsDebugging;

				case "Break":
					return debugger.IsDebugging;

				case "Continue":
					return /* debugger.HasStarted && */ !debugger.IsDebugging;

				case "DeleteAllBreakpoints":
					return DebugService.GetBreakpointsCount() > 0;
			}

			return true;
		}

		public event EventHandler CanExecuteChanged;
		protected virtual void OnCanExecuteChanged()
		{
			if (CanExecuteChanged != null)
			{
				CanExecuteChanged(this, new EventArgs());
			}
		}

		public void Execute(object parameter)
		{
			var debugger = DebugService.CurrentProjectDebugger;
			if (debugger == null)
			{
				return;
			}

			var command = parameter as string;
			switch (command)
			{
				case "Start":
					debugger.Start();
					break;

				case "Stop":
					debugger.Stop();
					break;

				case "Step":
					debugger.StepInto();
					break;

				case "Break":
					debugger.Break();
					break;

				case "Continue":
					debugger.Continue();
					break;

				case "Breakpoint":
					DebugService.ToggleBreakpointAtCaret();
					break;

				case "DeleteAllBreakpoints":
					DebugService.DeleteAllBreakpoints();
					break;

				case "CheckCode":
					BuildService.CheckCode();
					break;
			}
		}
		#endregion
	}
}
